home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2001 December / pcwk12201b.iso / Wersje pelne i specjalne / Winamp 2.77 i 3.0beta / wasabi-sdk_beta1.exe / studio / common / std.cpp < prev    next >
C/C++ Source or Header  |  2001-10-08  |  29KB  |  1,170 lines

  1. /*
  2.  
  3.   Nullsoft WASABI Source File License
  4.  
  5.   Copyright 1999-2001 Nullsoft, Inc.
  6.  
  7.     This software is provided 'as-is', without any express or implied
  8.     warranty.  In no event will the authors be held liable for any damages
  9.     arising from the use of this software.
  10.  
  11.     Permission is granted to anyone to use this software for any purpose,
  12.     including commercial applications, and to alter it and redistribute it
  13.     freely, subject to the following restrictions:
  14.  
  15.     1. The origin of this software must not be misrepresented; you must not
  16.        claim that you wrote the original software. If you use this software
  17.        in a product, an acknowledgment in the product documentation would be
  18.        appreciated but is not required.
  19.     2. Altered source versions must be plainly marked as such, and must not be
  20.        misrepresented as being the original software.
  21.     3. This notice may not be removed or altered from any source distribution.
  22.  
  23.  
  24.   Brennan Underwood
  25.   brennan@nullsoft.com
  26.  
  27. */
  28.  
  29. #ifdef FORTIFY
  30. #include "../studio/fortify/gfortify.h"
  31. #include "../studio/fortify/fortify.h"
  32. #endif
  33.  
  34. #include "std.h"
  35. #include <multimon.h>
  36. #ifdef WIN32
  37. #include <objbase.h>
  38. #endif
  39. #include "../studio/assert.h"
  40.  
  41. #include "ptrlist.h"
  42.  
  43. #ifndef _NOSTUDIO
  44. #include "pathparse.h"
  45. #include "../studio/api.h"
  46. #endif
  47.  
  48. #include "time.h"    // CUT if possible
  49.  
  50. //#define USE_MALLOC
  51. //#define COUNTUSAGE
  52.  
  53. #ifdef USE_MALLOC
  54. #include <malloc.h>
  55. #endif
  56.  
  57. #ifdef COUNTUSAGE
  58. static totalMem=0;
  59. #endif
  60.  
  61. void *DO_MALLOC(int size FORTIFY_INFO) {
  62.   ASSERT(size > 0);
  63.   if (size <= 0) return NULL;
  64.  
  65. #ifdef COUNTUSAGE
  66.   totalMem+=size;
  67. #endif
  68.  
  69. #ifndef FORTIFY //FG> anyone knows a way to translate defines inside macros so i can use FORTIFY_PARAMS ?
  70.  #ifndef USE_MALLOC
  71.   return GlobalAlloc(GPTR, size);
  72.  #else
  73.   void *p = malloc(size);
  74.   memset(p, 0, size);
  75.   return p;
  76.  #endif
  77. #else
  78.  #ifndef SE_MALLOC
  79.   return GlobalAlloc(GPTR, size , file, line);
  80.  #else
  81.   void *p = malloc(size, file, line);
  82.   memset(p, 0, size);
  83.   return p;
  84.  #endif
  85. #endif
  86. }
  87.               
  88. void *DO_CALLOC(int records, int recordsize FORTIFY_INFO) {
  89.   ASSERT(records > 0 && recordsize > 0);
  90.   return DO_MALLOC(records * recordsize FORTIFY_PARAMS);
  91. }
  92.  
  93. void DO_FREE(void *ptr FORTIFY_INFO) {
  94.   if (ptr == NULL) return;
  95.  
  96. #ifdef COUNTUSAGE
  97.  #ifndef USE_MALLOC
  98.   totalMem-=GlobalSize(ptr);
  99.  #else
  100.   totalMem-=_msize(ptr);
  101.  #endif
  102. #endif
  103.  
  104. #ifndef FORTIFY 
  105.  #ifndef USE_MALLOC
  106.   GlobalFree(ptr);
  107.  #else
  108.   free(ptr);
  109.  #endif
  110. #else
  111.  #ifndef USE_MALLOC
  112.   GlobalFree(ptr, file, line); // FG> same as GlobalAlloc here, i'd like a way to translate my define inside the macro
  113.  #else
  114.   free(ptr, file, line);
  115.  #endif
  116. #endif
  117. }
  118.  
  119. // Note: MEMCPY allows dest and src to overlap
  120. void MEMCPY(void *dest, const void *src, int n) {
  121.   if (n == 0) return;
  122.   ASSERT(dest != NULL);
  123.   ASSERT(src != NULL);
  124.   ASSERT(n >= 0);
  125.   MoveMemory(dest, src, n);
  126. }
  127.  
  128. void *DO_MEMDUP(const void *src, int n FORTIFY_INFO) {
  129.   void *ret;
  130.   ASSERT(n >= 0);
  131.   if (src == NULL || n == 0) return NULL;
  132.   ret = DO_MALLOC(n FORTIFY_PARAMS);
  133.   if (ret == NULL) return NULL;
  134.   MEMCPY(ret, src, n);
  135.   return ret;
  136. }
  137.  
  138. void *DO_REALLOC(void *ptr, int size FORTIFY_INFO) {
  139.   ASSERT(size >= 0);
  140.   if (size == 0) {
  141.     DO_FREE(ptr);
  142.     return NULL;
  143.   }
  144.   if(ptr == NULL) return DO_MALLOC(size);
  145.  
  146.   void *r; 
  147.  
  148. #ifdef COUNTUSAGE
  149.  #ifndef USE_MALLOC
  150.   totalMem-=GlobalSize(ptr);
  151.  #else
  152.   totalMem-=_msize(ptr);
  153.  #endif
  154. #endif
  155.  
  156. #ifndef FORTIFY
  157.  #ifndef USE_MALLOC
  158.   r = GlobalReAlloc((HGLOBAL)ptr, size, GMEM_ZEROINIT);
  159.  #else
  160.   int oldsize = _msize(ptr);
  161.   r = realloc(ptr, size);
  162.  #endif
  163. #else
  164.  #ifndef USE_MALLOC
  165.   r = GlobalReAlloc((HGLOBAL)ptr, size, file, line);
  166.  #else
  167.   int oldsize = _msize(ptr);
  168.   r = realloc(ptr, size, file, line);
  169.  #endif
  170. #endif
  171.   if (!r) { // realloc failed
  172.     void *newblock = MALLOC(size);
  173. #ifndef USE_MALLOC
  174.     int s = GlobalSize(ptr);
  175. #else
  176.     int s = _msize(ptr);
  177. #endif
  178.     MEMCPY(newblock, ptr, s);
  179.     FREE(ptr);
  180.     r = newblock;
  181.   } 
  182.  
  183. #ifdef COUNTUSAGE
  184.  #ifndef USE_MALLOC
  185.   totalMem+=size;
  186.  #else
  187.   totalMem+=size;
  188.  #endif
  189. #endif
  190.  
  191.   #ifdef USE_MALLOC
  192.    if (size > oldsize)
  193.     MEMZERO((char *)r+oldsize, size-oldsize);
  194.   #endif
  195.   return r;
  196. }
  197.  
  198. void MEMZERO(void *dest, int nbytes) {
  199.   ZeroMemory(dest, nbytes);
  200. }
  201.  
  202. void MEMSET(void *dest, char c, int n) {
  203.   ASSERT(n >= 0);
  204.   FillMemory(dest, n, c);
  205. }
  206.  
  207. int MEMCMP( const void *buf1, const void *buf2, int count ) {
  208.   return memcmp(buf1,buf2,count);
  209. }
  210.  
  211. #if 0
  212. int TOUPPER(int c) {
  213.   if (c >= 'a' && c <= 'z') c = (c - 'a') + 'A';
  214.   return c;
  215. }
  216.  
  217. int TOLOWER(int c) {
  218.   if (c >= 'A' && c <= 'Z') c = (c - 'A') + 'a';
  219.   return c;
  220. }
  221.  
  222. int ISDIGIT(int c) {
  223.   return (c >= '0' && c <= '9');
  224. }
  225.  
  226. int ISALPHA(int c) {
  227.   return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
  228. }
  229. #endif
  230.  
  231. char *DO_STRDUP(const char *ptr FORTIFY_INFO) {
  232.   char *ret;
  233.   if (ptr == NULL) return NULL;
  234.   ret = (char *)DO_MALLOC(STRLEN(ptr)+1 FORTIFY_PARAMS);
  235.   if (ret != NULL) {
  236.     STRCPY(ret, ptr);
  237.   }
  238.   return ret;
  239. }
  240.  
  241. int STRLEN(const char *str) {
  242.   if (!str) return 0;
  243. #ifdef WIN32
  244.   return lstrlen(str);
  245. #else
  246.   int r = 0;
  247.   while (*str++ != 0) r++;
  248.   return r;
  249. #endif
  250. }
  251.  
  252. int STRCMP(const char *str1, const char *str2) {
  253.   ASSERT(str1!=NULL);
  254.   ASSERT(str2!=NULL);
  255. #ifdef WIN32
  256. #if 0
  257.   if (!str1 && !str2) return 0;
  258.   if (!str1 && str2) return 1;
  259.   if (!str2) return -1;
  260. #endif
  261.   return lstrcmp(str1, str2);
  262. #else
  263. #error implement me
  264. #endif
  265. }
  266.  
  267. int STRICMP(const char *str1, const char *str2) {
  268.   ASSERT(str1!=NULL);
  269.   ASSERT(str2!=NULL);
  270. #if 0
  271.   if (!str1 && !str2) return 0;
  272.   if (!str1 && str2) return 1;
  273.   if (!str2) return -1;
  274. #endif
  275.   return lstrcmpi(str1, str2);
  276. }
  277.  
  278. int STRNCMP(const char *str1, const char *str2, int l) {
  279.   ASSERT(str1!=NULL);
  280.   ASSERT(str2!=NULL);
  281. #ifdef WIN32
  282. #if 0
  283.   if (!str1 && !str2) return 0;
  284.   if (!str1 && str2) return 1;
  285.   if (!str2) return -1;
  286. #endif
  287.   return strncmp(str1, str2, l);
  288. #else
  289. #error implement me
  290. #endif
  291. }
  292.  
  293. int STRNNCMP(const char *str1, const char *str2) {
  294.   ASSERT(str1!=NULL);
  295.   ASSERT(str2!=NULL);
  296.   return STRNCMP(str1, str2, STRLEN(str2));
  297. }
  298.  
  299. //FG> sorry brennan, this need to not be a const :)
  300. void STRTOUPPER(char *p) {
  301.   while (*p) {
  302.     *p = TOUPPER(*p);
  303.     p++;
  304.   }
  305. }
  306.  
  307. void STRTOLOWER(char *p) {
  308.   while (*p) {
  309.     *p = TOLOWER(*p);
  310.     p++;
  311.   }
  312. }
  313.  
  314. int STRNICMP(const char *str1, const char *str2, int l) {
  315.   ASSERT(str1!=NULL);
  316.   ASSERT(str2!=NULL);
  317.  
  318.   ASSERT(l>=0);
  319.   while (TOUPPER(*str1) == TOUPPER(*str2) && *str1 != 0 && *str2 != 0 && l--)
  320.     str1++, str2++;
  321.   if (l == 0) return 0;
  322.   return (*str2 - *str1);
  323. }
  324.  
  325. int STRNINCMP(const char *str1, const char *str2) {
  326.   ASSERT(str1!=NULL);
  327.   ASSERT(str2!=NULL);
  328.   return STRNICMP(str1, str2, STRLEN(str2));
  329. }
  330.  
  331. int STRNCASEEQL(const char *str1, const char *str2, int l) {
  332.   ASSERT(str1!=NULL);
  333.   ASSERT(str2!=NULL);
  334.   return STRNICMP(str1, str2, l) == 0;
  335. }
  336.  
  337. int STREQL(const char *str1, const char *str2) {
  338.   ASSERT(str1!=NULL);
  339.   ASSERT(str2!=NULL);
  340. #ifdef WIN32
  341.   return (lstrcmp(str1, str2)==0);
  342. #else
  343.   return (strcmp(str1, str2) == 0);
  344. #endif
  345. }
  346.  
  347. int STRCASEEQL(const char *str1, const char *str2) {
  348.   ASSERT(str1!=NULL);
  349.   ASSERT(str2!=NULL);
  350. #ifdef WIN32
  351.   return lstrcmpi(str1, str2)==0;
  352. #else
  353.   while (TOUPPER(*str1) == TOUPPER(*str2) && *str1 != 0 && *str2 != 0)
  354.     str1++, str2++;
  355.   return *str1 == *str2;
  356. #endif
  357. }
  358.  
  359. char TOUPPERANDSLASH(char a) {
  360.   a = TOUPPER(a);
  361.   if (a=='\\') a='/';
  362.   return a;    
  363. }
  364.  
  365. int PATHEQL(const char *str1, const char *str2) {
  366. //NONPORTABLE
  367.   if (str1 == NULL) {
  368.     if (str2 == NULL) return TRUE;
  369.     return FALSE;
  370.   }
  371.   while (TOUPPERANDSLASH(*str1) == TOUPPERANDSLASH(*str2) && *str1 != 0 && *str2 != 0) str1++, str2++;
  372.   return *str1 == *str2;
  373. }
  374.  
  375. char *STRSTR(const char *str1, const char *str2) {
  376.   ASSERT(str1!=NULL);
  377.   ASSERT(str2!=NULL);
  378.   return strstr(str1, str2);
  379. }
  380.  
  381. char *STRCASESTR(const char *str1, const char *str2) {
  382.   ASSERT(str1!=NULL);
  383.   ASSERT(str2!=NULL);
  384.   char *p;
  385.   int len = STRLEN(str2);
  386.   for (p = (char *)str1; *p; p++) {
  387.     if (STRNCASEEQL(p, str2, len)) return p;
  388.   }
  389.   return NULL;
  390. }
  391.  
  392. int STRCASERPL(char *s, const char *w, const char *r, int maxsize) {
  393.  
  394.   int rl = STRLEN(r);
  395.   int wl = STRLEN(w);
  396.   int gain = rl - wl;
  397.   int i=0;
  398.   char *o = s;
  399.  
  400.   while (1) {
  401.     char *f = STRCASESTR(o, w);
  402.     if (!f) break;
  403.     int pos = s - f;
  404.     if (pos + wl + gain >= maxsize) break;
  405.     if (gain < 0) {
  406.       MEMCPY(f+wl+gain, f+wl, maxsize - pos - wl);
  407.       s[maxsize-1] = 0;
  408.     }
  409.     else if (gain > 0) {
  410.       MEMCPY(f+wl+gain, f+wl, maxsize - pos - wl - gain);
  411.       s[maxsize-1] = 0;
  412.     }
  413.     i++;    
  414.     MEMCPY(f, r, rl);
  415.     o = f+rl;
  416.   }
  417.   return i;
  418. }
  419.  
  420. void STRCPY(char *dest, const char *src) {
  421.   ASSERT(dest != NULL);
  422.   ASSERT(src != NULL);
  423. #ifdef WIN32
  424.   lstrcpy(dest, src);
  425. #else
  426.   strcpy(dest, src);
  427. #endif
  428. }
  429.  
  430. void STRNCPY(char *dest, const char *src, int maxchar) {
  431.   ASSERT(dest != NULL);
  432.   ASSERT(src != NULL);
  433.   strncpy(dest, src, maxchar);
  434. }
  435.  
  436. char *STRCHR(const char *str, int c) {
  437.   ASSERT(str != NULL);
  438.   return strchr(str, c);
  439. }
  440.  
  441. void STRCAT(char *dest, const char *append) {
  442.   ASSERT(dest != NULL);
  443.   ASSERT(append != NULL);
  444. #ifdef WIN32
  445.   lstrcat(dest, append);
  446. #else
  447.   strcat(dest, append);
  448. #endif
  449. }
  450.  
  451. unsigned long STRTOUL(const char *s, char **p, int rx) {
  452.   ASSERT(s != NULL);
  453.   ASSERT(p != NULL);
  454.   return strtoul(s,p,rx);
  455. }
  456.  
  457. #ifdef NS_TRANSCENDENTALS
  458. #        ifdef NS_REAL_DEFINED
  459. #        include <math.h>
  460.         Real SIN( Real a ) {
  461.             return sin( a );
  462.         }
  463.         Real COS( Real a ) {
  464.             return cos( a );
  465.         }
  466. #        endif//NS_REAL_DEFINED
  467. #endif//NS_TRANSCENDENTALS
  468.  
  469. static Std blep;
  470. static int rand_inited;
  471.  
  472. static double divider=0.;
  473.  
  474. Std::Std() {
  475.   LARGE_INTEGER ll;
  476.   QueryPerformanceFrequency(&ll);
  477.   divider = (double)ll.QuadPart;
  478. }
  479.  
  480. void Std::getMousePos(POINT *p) {
  481.   ASSERT(p != NULL);
  482.   GetCursorPos(p);
  483. }
  484.  
  485. void Std::getMousePos(int *x, int *y) {
  486.   POINT p;
  487.   getMousePos(&p);
  488.   if (x != NULL) *x = p.x;
  489.   if (y != NULL) *y = p.y;
  490. }
  491.  
  492. void Std::getMousePos(long *x, long *y) {
  493.   getMousePos((int *)x, (int *)y);
  494. }
  495.  
  496. void Std::setMousePos(POINT *p) {
  497.   ASSERT(p != NULL);
  498.   SetCursorPos(p->x, p->y);
  499. }
  500.  
  501. void Std::setMousePos(int x, int y) {
  502.   POINT p={x,y};
  503.   setMousePos(&p);
  504. }
  505.  
  506. void Std::getViewport(RECT *r, POINT *p) {
  507.   getViewport(r, p, NULL, NULL);
  508. }
  509.  
  510. void Std::getViewport(RECT *r, RECT *sr) {
  511.   getViewport(r, NULL, sr, NULL);
  512. }
  513.  
  514. void Std::getViewport(RECT *r, HWND wnd) {
  515.   getViewport(r, NULL, NULL, wnd);
  516. }
  517.  
  518. void Std::getViewport(RECT *r, POINT *p, RECT *sr, HWND wnd) {
  519.   ASSERT(r != NULL);
  520.     if (p || sr || wnd) {
  521.       HINSTANCE h=LoadLibrary("user32.dll");
  522.       if (h) {
  523.             HMONITOR (WINAPI *Mfp)(POINT pt, DWORD dwFlags) = (HMONITOR (WINAPI *)(POINT,DWORD)) GetProcAddress(h,"MonitorFromPoint");
  524.       HMONITOR (WINAPI *Mfr)(LPCRECT lpcr, DWORD dwFlags) = (HMONITOR (WINAPI *)(LPCRECT, DWORD)) GetProcAddress(h, "MonitorFromRect");
  525.       HMONITOR (WINAPI *Mfw)(HWND wnd, DWORD dwFlags)=(HMONITOR (WINAPI *)(HWND, DWORD)) GetProcAddress(h, "MonitorFromWindow");
  526.       BOOL (WINAPI *Gmi)(HMONITOR mon, LPMONITORINFO lpmi) = (BOOL (WINAPI *)(HMONITOR,LPMONITORINFO)) GetProcAddress(h,"GetMonitorInfoA");    
  527.             if (Mfp && Mfr && Mfw && Gmi) {
  528.               HMONITOR hm;
  529.               if (p)
  530.                   hm=Mfp(*p,MONITOR_DEFAULTTONULL);
  531.                 else if (sr)
  532.                   hm=Mfr(sr,MONITOR_DEFAULTTONULL);
  533.                 else if (wnd)
  534.                   hm=Mfw(wnd,MONITOR_DEFAULTTONULL);
  535.         if (hm) {
  536.           MONITORINFOEX mi;
  537.           MEMZERO(&mi,sizeof(mi));
  538.           mi.cbSize=sizeof(mi);
  539.  
  540.           if (Gmi(hm,&mi)) {
  541.             *r=mi.rcWork;
  542.             return;
  543.           }          
  544.         }
  545.             }
  546.             FreeLibrary(h);
  547.         }
  548.     }
  549.   SystemParametersInfo(SPI_GETWORKAREA,0,r,0);
  550. }
  551.  
  552. int Std::pointInRect(RECT *r, POINT &p) {
  553.   if (p.x < r->left ||
  554.       p.x >= r->right ||
  555.       p.y < r->top ||
  556.       p.y >= r->bottom) return 0;
  557.   return 1;
  558. }
  559.  
  560. int Std::random() {
  561.   if (!rand_inited++)
  562.     srand(time(NULL));
  563.   return rand();
  564. }
  565.  
  566. void Std::usleep(int ms) {
  567.   Sleep(ms);
  568. }
  569.  
  570. stdtimeval Std::getTimeStamp() {
  571.   return time(NULL);
  572. }
  573.  
  574. stdtimevalms Std::getTimeStampMS() {
  575.   LARGE_INTEGER ll;
  576.   if (!QueryPerformanceCounter(&ll)) return GetTickCount(); // jf
  577.   stdtimevalms ret = (stdtimevalms)ll.QuadPart;
  578.   return ret /= divider;
  579. }
  580.  
  581. DWORD Std::getTickCount() {
  582.   return GetTickCount();
  583. }
  584.  
  585. void Std::tolowerString(char *str) {
  586.   while (*str++) *str = TOLOWER(*str);
  587. }
  588.  
  589. void Std::ensureVisible(RECT *r) {
  590.   RECT sr;
  591.   POINT p={(r->right+r->left)/2,(r->bottom+r->top)/2};
  592.   Std::getViewport(&sr,&p);
  593.   int w = r->right-r->left;
  594.   int h = r->bottom-r->top;
  595.   if (r->bottom > sr.bottom) {
  596.     r->bottom = sr.bottom;
  597.     r->top = r->bottom-h;
  598.   }
  599.   if (r->right > sr.right) {
  600.     r->right = sr.right;
  601.     r->left = r->right-w;
  602.   }
  603.   if (r->left < sr.left) {
  604.     r->left = sr.left;
  605.     r->right = r->left+w;
  606.   }
  607.   if (r->top < sr.top) {
  608.     r->top = sr.top;
  609.     r->bottom = r->top+h;
  610.   }
  611. }
  612.  
  613. int Std::getScreenWidth() {
  614.   RECT r;
  615.     SystemParametersInfo(SPI_GETWORKAREA,0,&r,0);
  616.   return r.right-r.left;
  617. }
  618.  
  619. int Std::getScreenHeight() {
  620.   RECT r;
  621.     SystemParametersInfo(SPI_GETWORKAREA,0,&r,0);
  622.   return r.bottom-r.top;
  623. }
  624.  
  625. int Std::messageBox(char *txt, char *title, int flags) {
  626. return MessageBox(NULL, txt, title, flags);
  627. }
  628.  
  629. int Std::getDoubleClickDelay() {
  630.   return GetDoubleClickTime();
  631. }
  632.  
  633. #undef GetSystemMetrics //FG> DUH!
  634. int Std::getDoubleClickX() {
  635.   return GetSystemMetrics(SM_CYDOUBLECLK);
  636. }
  637.  
  638. int Std::getDoubleClickY() {
  639.   return GetSystemMetrics(SM_CXDOUBLECLK);
  640. }
  641.  
  642. const char *Std::scanstr_back(const char *str, const char *toscan, const char *defval) {
  643.     const char *s=str+STRLEN(str)-1;
  644.     if (STRLEN(str) < 1) return defval;
  645.     if (STRLEN(toscan) < 1) return defval;
  646.     while (1) {
  647.         const char *t=toscan;
  648.         while (*t)
  649.             if (*t++ == *s) return s;
  650.         t=CharPrev(str,s);
  651.         if (t==s) return defval;
  652.         s=t;
  653.     }
  654. }
  655.  
  656. const char *Std::extension(const char *fn) {
  657.   const char *s = scanstr_back(fn,".\\/",fn-1);
  658.   if (s < fn) return "";
  659.   if (*s == '\\' || *s == '/') return "";
  660.   return (s+1);
  661. }
  662.  
  663. const char *Std::filename(const char *fn) {
  664.   const char *s=scanstr_back(fn,"\\/",0);
  665.   if(!s) return fn;
  666.   return (s+1);
  667. }
  668.  
  669. BOOL Std::isMatchPattern(const char *p) {
  670.   while (*p) {
  671.     switch (*p++) {
  672.       case '?':
  673.       case '*':
  674.       case '[':
  675.       case '\\':
  676.         return TRUE;
  677.     }
  678.   }
  679.   return FALSE;
  680. }
  681.  
  682. BOOL Std::isValidMatchPattern(const char *p, int *error_type) {
  683.   /* init error_type */
  684.   *error_type = PATTERN_VALID;
  685.   /* loop through pattern to EOS */
  686.   while (*p) {
  687.     /* determine pattern type */
  688.     switch (*p) {
  689.       /* check literal escape, it cannot be at end of pattern */
  690.       case '\\':
  691.               if (!*++p) {
  692.           *error_type = PATTERN_ESC;
  693.           return FALSE;
  694.         }
  695.         p++;
  696.         break;
  697.       /* the [..] construct must be well formed */
  698.       case '[':
  699.         p++;
  700.         /* if the next character is ']' then bad pattern */
  701.         if (*p == ']') {
  702.           *error_type = PATTERN_EMPTY;
  703.           return FALSE;
  704.         }
  705.         /* if end of pattern here then bad pattern */
  706.         if (!*p) {
  707.           *error_type = PATTERN_CLOSE;
  708.           return FALSE;
  709.         }
  710.         /* loop to end of [..] construct */
  711.         while (*p != ']') {
  712.           /* check for literal escape */
  713.           if (*p == '\\') {
  714.             p++;
  715.             /* if end of pattern here then bad pattern */
  716.             if (!*p++) {
  717.               *error_type = PATTERN_ESC;
  718.               return FALSE;
  719.             }
  720.           } else p++;
  721.         /* if end of pattern here then bad pattern */
  722.         if (!*p) {
  723.           *error_type = PATTERN_CLOSE;
  724.           return FALSE;
  725.         }
  726.         /* if this a range */
  727.         if (*p == '-') {
  728.           /* we must have an end of range */
  729.                     if (!*++p || *p == ']') {
  730.             *error_type = PATTERN_RANGE;
  731.             return FALSE;
  732.           } else {
  733.             /* check for literal escape */
  734.             if (*p == '\\') p++;
  735.             /* if end of pattern here then bad pattern */
  736.             if (!*p++) {
  737.               *error_type = PATTERN_ESC;
  738.               return FALSE;
  739.             }
  740.           }
  741.         }
  742.       }
  743.       break;
  744.       /* all other characters are valid pattern elements */
  745.       case '*':
  746.       case '?':
  747.       default:
  748.         p++; /* "normal" character */
  749.         break;
  750.     }
  751.   }
  752.   return TRUE;
  753. }
  754.  
  755. int Std::matche(register const char *p, register const char *t) {
  756.   register char range_start, range_end;  /* start and end in range */
  757.  
  758.   BOOLEAN invert;             /* is this [..] or [!..] */
  759.   BOOLEAN member_match;       /* have I matched the [..] construct? */
  760.   BOOLEAN loop;               /* should I terminate? */
  761.  
  762.   for ( ; *p; p++, t++) {
  763.     /* if this is the end of the text then this is the end of the match */
  764.     if (!*t) {
  765.       return ( *p == '*' && *++p == '\0' ) ? MATCH_VALID : MATCH_ABORT;
  766.     }
  767.     /* determine and react to pattern type */
  768.     switch (*p) {
  769.       case '?': /* single any character match */
  770.         break;
  771.             case '*': /* multiple any character match */
  772.         return matche_after_star (p, t);
  773.  
  774.       /* [..] construct, single member/exclusion character match */
  775.       case '[': {
  776.         /* move to beginning of range */
  777.         p++;
  778.         /* check if this is a member match or exclusion match */
  779.         invert = FALSE;
  780.         if (*p == '!' || *p == '^') {
  781.           invert = TRUE;
  782.           p++;
  783.         }
  784.         /* if closing bracket here or at range start then we have a malformed pattern */
  785.         if (*p == ']') return MATCH_PATTERN;
  786.  
  787.         member_match = FALSE;
  788.         loop = TRUE;
  789.         while (loop) {
  790.           /* if end of construct then loop is done */
  791.           if (*p == ']') {
  792.             loop = FALSE;
  793.             continue;
  794.           }
  795.           /* matching a '!', '^', '-', '\' or a ']' */
  796.           if (*p == '\\') range_start = range_end = *++p;
  797.           else  range_start = range_end = *p;
  798.           /* if end of pattern then bad pattern (Missing ']') */
  799.           if (!*p) return MATCH_PATTERN;
  800.           /* check for range bar */
  801.           if (*++p == '-') {
  802.             /* get the range end */
  803.             range_end = *++p;
  804.             /* if end of pattern or construct then bad pattern */
  805.             if (range_end == '\0' || range_end == ']') return MATCH_PATTERN;
  806.                       /* special character range end */
  807.             if (range_end == '\\') {
  808.               range_end = *++p;
  809.               /* if end of text then we have a bad pattern */
  810.               if (!range_end) return MATCH_PATTERN;
  811.             }
  812.             /* move just beyond this range */
  813.             p++;
  814.           }
  815.           /* if the text character is in range then match found.
  816.              make sure the range letters have the proper
  817.              relationship to one another before comparison */
  818.           if (range_start < range_end) {
  819.             if (*t >= range_start && *t <= range_end) {
  820.               member_match = TRUE;
  821.               loop = FALSE;
  822.             }
  823.           } else {
  824.             if (*t >= range_end && *t <= range_start) {
  825.               member_match = TRUE;
  826.               loop = FALSE;
  827.             }
  828.           }
  829.         }
  830.         /* if there was a match in an exclusion set then no match */
  831.         /* if there was no match in a member set then no match */
  832.         if ((invert && member_match) || !(invert || member_match)) return MATCH_RANGE;
  833.         /* if this is not an exclusion then skip the rest of the [...] construct that already matched. */
  834.         if (member_match) {
  835.           while (*p != ']') {
  836.             /* bad pattern (Missing ']') */
  837.             if (!*p) return MATCH_PATTERN;
  838.             /* skip exact match */
  839.             if (*p == '\\') {
  840.               p++;
  841.                           /* if end of text then we have a bad pattern */
  842.               if (!*p) return MATCH_PATTERN;
  843.             }
  844.             /* move to next pattern char */
  845.             p++;
  846.                     }
  847.                 }
  848.         break;
  849.       }
  850.       case '\\':  /* next character is quoted and must match exactly */
  851.         /* move pattern pointer to quoted char and fall through */
  852.         p++;
  853.         /* if end of text then we have a bad pattern */
  854.         if (!*p) return MATCH_PATTERN;
  855.         /* must match this character exactly */
  856.       default:
  857.         if (toupper(*p) != toupper(*t)) return MATCH_LITERAL;
  858.     }
  859.   }
  860.     /* if end of text not reached then the pattern fails */
  861.   if (*t) return MATCH_END;
  862.   else return MATCH_VALID;
  863. }
  864.  
  865. int Std::matche_after_star(register const char *p, register const char *t) {
  866.   register int match = 0;
  867.   register nextp;
  868.   /* pass over existing ? and * in pattern */
  869.   while ( *p == '?' || *p == '*' ) {
  870.     /* take one char for each ? and + */
  871.     if (*p == '?') {
  872.       /* if end of text then no match */
  873.       if (!*t++) return MATCH_ABORT;
  874.     }
  875.     /* move to next char in pattern */
  876.     p++;
  877.   }
  878.   /* if end of pattern we have matched regardless of text left */
  879.   if (!*p) return MATCH_VALID;
  880.   /* get the next character to match which must be a literal or '[' */
  881.   nextp = *p;
  882.   if (nextp == '\\') {
  883.     nextp = p[1];
  884.     /* if end of text then we have a bad pattern */
  885.     if (!nextp) return MATCH_PATTERN;
  886.   }
  887.   /* Continue until we run out of text or definite result seen */
  888.   do {
  889.     /* a precondition for matching is that the next character
  890.        in the pattern match the next character in the text or that
  891.        the next pattern char is the beginning of a range.  Increment
  892.        text pointer as we go here */
  893.     if (tolower(nextp) == tolower(*t) || nextp == '[') match = matche(p, t);
  894.     /* if the end of text is reached then no match */
  895.     if (!*t++) match = MATCH_ABORT;
  896.   } while ( match != MATCH_VALID && match != MATCH_ABORT && match != MATCH_PATTERN);
  897.   /* return result */
  898.   return match;
  899. }
  900.  
  901. BOOL Std::match(const char *p, const char *t) {
  902.   int error_type;
  903.   error_type = matche(p,t);
  904.   return (error_type == MATCH_VALID ) ? TRUE : FALSE;
  905. }
  906.  
  907. #ifndef _NOSTUDIO
  908.  
  909. #undef fopen
  910. #undef fclose
  911. #undef fseek
  912. #undef ftell
  913. #undef fread
  914. #undef fwrite
  915. #undef fgets
  916. #undef fprintf
  917. static PtrList<void> fileReaders;
  918. FILE *FOPEN(const char *filename,const char *mode)
  919. {
  920.   if (!STRNINCMP(filename, "file:")) filename += STRLEN("file:");
  921.     FILE *ret=fopen(filename,mode);
  922.     if(ret) return ret;
  923.  
  924.     // File not found... try to open it with the file readers
  925.     // but before that, resolve ".." in path so zip can
  926.     // find it
  927.  
  928.     const char *rFilename = filename;
  929.   char str[WA_MAX_PATH]="";
  930.  
  931.   if (STRSTR(filename, "..")) {
  932.     PathParser pp(filename);
  933.     for (int i=0;i<pp.getNumStrings();i++) {
  934.       if (STREQL(pp.enumString(i), "..")) {
  935.         PathParser pp2(str);
  936. if (pp2.getNumStrings() <= 0) return NULL;
  937.         ASSERTPR(pp2.getNumStrings() > 0, "we don't handle this right, and I'm not sure how to fix it because I'm not sure what the code should do with a leading .. --BU");
  938.         int l = STRLEN(pp2.enumString(pp2.getNumStrings()-1));
  939.         str[STRLEN(str)-l-1]=0;
  940.         continue;
  941.       }
  942.       if (STREQL(pp.enumString(i), ".")) 
  943.         continue;
  944.       STRCAT(str, pp.enumString(i));
  945.       STRCAT(str, "/");
  946.     }
  947.   str[STRLEN(str)-1]=0;
  948.   rFilename = str;
  949.   }
  950.  
  951.   if(api && (ret=(FILE *)api->fileOpen(rFilename,mode))) {
  952.     fileReaders.addItem((void *)ret);
  953.     return ret;
  954.   }
  955.  
  956.     // File still not found ...
  957. #ifdef _DEBUG
  958.     char tmp[512];
  959.     wsprintf(tmp,"Warning: can't open %s\n",filename);
  960.     OutputDebugString(tmp);
  961. #endif
  962.     return 0;
  963. }
  964.  
  965. int FCLOSE(FILE *stream)
  966. {
  967.     if(fileReaders.searchItem((void *)stream)!=-1) {
  968.         fileReaders.removeItem((void *)stream);
  969.         api->fileClose((void *)stream);
  970.         return 0;
  971.     } 
  972.     return fclose(stream);
  973. }
  974.  
  975. int FSEEK(FILE *stream, long offset, int origin)
  976. {
  977.     if(fileReaders.searchItem((void *)stream)!=-1) return api->fileSeek(offset, origin,(void *)stream);
  978.     return fseek(stream,offset,origin);
  979. }
  980.  
  981. long FTELL(FILE *stream)
  982. {
  983.     if(fileReaders.searchItem((void *)stream)!=-1) return api->fileTell((void *)stream);
  984.     return ftell(stream);
  985. }
  986.  
  987. size_t FREAD(void *buffer, size_t size, size_t count, FILE *stream)
  988. {
  989.     if(fileReaders.searchItem((void *)stream)!=-1) return api->fileRead(buffer,size*count,(void *)stream);
  990.     return fread(buffer,size,count,stream);
  991. }
  992.  
  993. size_t FWRITE(const void *buffer, size_t size, size_t count, FILE *stream)
  994. {
  995.     if(fileReaders.searchItem((void *)stream)!=-1) return api->fileWrite(buffer,size*count,(void *)stream);
  996.     return fwrite(buffer,size,count,stream);
  997. }
  998.  
  999. int FGETSIZE(FILE *stream) {
  1000.     if(fileReaders.searchItem((void *)stream)!=-1) return api->fileGetFileSize((void *)stream);
  1001.     int p = ftell(stream);
  1002.     fseek(stream, 0, SEEK_END);
  1003.     int s = ftell(stream);
  1004.     fseek(stream, p, SEEK_SET);
  1005.     return s;
  1006. }
  1007.  
  1008. char *FGETS( char *string, int n, FILE *stream )
  1009. {
  1010.     if(fileReaders.searchItem((void *)stream)!=-1) {
  1011.       ASSERTPR(0, "filereader fgets not implemented");
  1012.   }
  1013.     return fgets(string,n,stream);
  1014. }
  1015.  
  1016. int FPRINTF( FILE *stream, const char *format , ...)
  1017. {
  1018.   va_list args;
  1019.     int ret;
  1020.   va_start (args, format);    
  1021.     ret=vfprintf(stream,format,args);
  1022.     va_end (args);
  1023.     return ret;
  1024. }
  1025.  
  1026. const char *TMPNAM2(char *string, int val) {
  1027.   char tempPath[WA_MAX_PATH];
  1028.   static char tempName[WA_MAX_PATH];
  1029.   GetTempPath(WA_MAX_PATH, tempPath);
  1030.   if (tempPath[STRLEN(tempPath)-1] != '\\')
  1031.     STRCAT(tempPath, "\\");
  1032.   GetTempFileName(tempPath,"DTC",val,tempName);
  1033.   if(string) {
  1034.     STRCPY(string,tempName);
  1035.     return string;
  1036.   } else
  1037.     return tempName;
  1038. }
  1039.  
  1040. const char *TMPNAM(char *string) {
  1041.   return TMPNAM2(string, 0);
  1042. }
  1043.  
  1044. int FEXISTS(const char *filename) {
  1045.   return api->fileExists(filename);
  1046. }
  1047.  
  1048. int UNLINK(const char *filename) {
  1049.   return api->fileRemove(filename);
  1050. }
  1051.  
  1052. int Std::getCurDir(char *str, int maxlen) {
  1053. #ifdef WIN32
  1054.   return GetCurrentDirectory(maxlen, str);
  1055. #else
  1056. #error port me!
  1057. #endif
  1058. }
  1059.  
  1060. int Std::setCurDir(const char *str) {
  1061. #ifdef WIN32
  1062.   return SetCurrentDirectory(str);
  1063. #else
  1064. #error port me!
  1065. #endif
  1066. }
  1067.  
  1068. void Std::GUIDprint(GUID &guid, char *str) {
  1069. #ifdef WIN32
  1070.   OLECHAR oguid[256]; // NONPORTABLE
  1071.   StringFromGUID2(guid, oguid, 256);
  1072.   wsprintf(str, "%$", oguid);
  1073. #else
  1074. #error port me!
  1075. #endif
  1076. }
  1077.  
  1078. THREADID Std::getCurrentThreadId() {
  1079. #ifdef WIN32
  1080.   return GetCurrentThreadId();
  1081. #else
  1082. #error port me!
  1083. #endif
  1084. }
  1085.  
  1086. void Std::getTempPath(int bufsize, char *dst) {
  1087. #ifdef WIN32
  1088.   GetTempPath(bufsize,dst);
  1089. #else
  1090. #error port me!
  1091. #endif
  1092. }
  1093.  
  1094. int Std::createDirectory(const char *dirname) {
  1095. #ifdef WIN32
  1096.   if(!CreateDirectory(dirname,NULL)) {
  1097.     // create all the path
  1098.     PathParser pp(dirname);
  1099.     int l=pp.getNumStrings();
  1100.     for(int i=2;i<=l;i++) {
  1101.       String dir;
  1102.       for(int j=0;j<i;j++) 
  1103.         dir+=StringPrintf("%s\\",pp.enumString(j));
  1104.       CreateDirectory(dir,NULL);
  1105.     }
  1106.   }
  1107.   return 1;
  1108. #else
  1109. #error port me!
  1110. #endif
  1111. }
  1112.  
  1113. int Std::getFileInfos(const char *filename, fileInfoStruct *infos) {
  1114. #ifdef WIN32
  1115.   // GetFileAttributesEx doesn't exist in win95 or nt3-4 ...
  1116. /*  WIN32_FILE_ATTRIBUTE_DATA fi;
  1117.   if(!GetFileAttributesEx(filename, GetFileExInfoStandard, &fi)) return 0;
  1118.   infos->fileSizeHigh=fi.nFileSizeHigh;
  1119.   infos->fileSizeLow=fi.nFileSizeLow;
  1120.   infos->lastWriteTimeHigh=fi.ftLastWriteTime.dwHighDateTime;
  1121.   infos->lastWriteTimeLow=fi.ftLastWriteTime.dwLowDateTime;*/
  1122.   HANDLE h;
  1123.   WIN32_FIND_DATA fd;
  1124.   if((h=FindFirstFile(filename, &fd))==INVALID_HANDLE_VALUE) return 0;
  1125.   infos->fileSizeHigh=fd.nFileSizeHigh;
  1126.   infos->fileSizeLow=fd.nFileSizeLow;
  1127.   infos->lastWriteTimeHigh=fd.ftLastWriteTime.dwHighDateTime;
  1128.   infos->lastWriteTimeLow=fd.ftLastWriteTime.dwLowDateTime;
  1129.   FindClose(h);
  1130.   return 1;
  1131. #else
  1132. #error port me!
  1133. #endif
  1134. }
  1135.  
  1136. void Std::removeDirectory(const char *buf, int recurse) {
  1137. #ifdef WIN32
  1138.   if (recurse) {
  1139.     HANDLE h;
  1140.     WIN32_FIND_DATA fd;
  1141.     char path[WA_MAX_PATH];
  1142.     STRCPY(path,buf);
  1143.     char *p=path;
  1144.     while (*p) p++;
  1145.     STRCPY(p,"\\*.*");
  1146.     h = FindFirstFile(path,&fd);
  1147.     if (h != INVALID_HANDLE_VALUE) {
  1148.       do {
  1149.         if (fd.cFileName[0] != '.' ||
  1150.             (fd.cFileName[1] != '.' && fd.cFileName[1])) {
  1151.           STRCPY(p+1,fd.cFileName);
  1152.           if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) 
  1153.             SetFileAttributes(path,fd.dwFileAttributes^FILE_ATTRIBUTE_READONLY);
  1154.           if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) removeDirectory(path,recurse);
  1155.           else DeleteFile(path);
  1156.         }
  1157.       } while (FindNextFile(h,&fd));
  1158.       FindClose(h);
  1159.     }
  1160.     p[0]=0; // fix buffer
  1161.   }
  1162.   RemoveDirectory(buf);
  1163. #else
  1164. #error port me!
  1165. #endif
  1166. }
  1167.  
  1168.  
  1169. #endif
  1170.